package com.itheima.appserver.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.appserver.excepiton.MyException;
import com.itheima.appserver.interceptor.UserThreadLocal;
import com.itheima.commons.constants.Constants;
import com.itheima.commons.model.domain.Question;
import com.itheima.commons.model.domain.UserInfo;
import com.itheima.commons.model.mongo.RecommendUser;
import com.itheima.commons.model.mongo.UserLike;
import com.itheima.commons.model.vo.*;
import com.itheima.dubbo.interfaces.QuestionApi;
import com.itheima.dubbo.interfaces.RecommendUserApi;
import com.itheima.dubbo.interfaces.UserLikeApi;
import com.itheima.dubbo.interfaces.UserLocationApi;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 探花相关的业务类
 */
@Service
public class TanhuaService {

    @Reference
    private RecommendUserApi recommendUserApi;

    @Reference
    private QuestionApi questionApi;

    @Reference
    private UserLocationApi userLocationApi;

    @Reference
    private UserLikeApi userLikeApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private VisitorsService visitorsService;

    @Autowired
    private HuanXinService hxService;

    /**
     * 查询今日佳人
     *
     * @return
     */
    public TodayBestVo todayBest() {
        // 1.解析Token 拿到登录人的ID  在拦截器中已经解析过了
        // 2.根据ID去查询最高分  Dubbo调用
        RecommendUser recommendUser = recommendUserApi.queryWithMaxScore(UserThreadLocal.getUserId());
        if (ObjectUtil.isNull(recommendUser)) {
            throw new MyException(ErrorResult.recommendUserIsEmpty());
        }

        // 3.根据最高分的人的id查询tb_user_info
        UserInfo userInfo = userInfoService.findUserInfoByUserId(recommendUser.getUserId());

        // 4.把第2步和第3步的结果集 合并成一个VO
        TodayBestVo todayBest = TodayBestVo.init(userInfo, recommendUser);
        return todayBest;
    }

    /**
     * 查询首页推荐列表
     *
     * @param params
     * @return
     */
    public PageResult recommendationList(Map<String, Object> params) {
        // 1.解析Token 拿到登录人的ID  在拦截器中已经解析过了
        // 2.根据ID去分页查询给这个用户推荐的所有用户
        PageResult pageResult = recommendUserApi.queryRecommendUserList(MapUtil.getInt(params, "page", 1),
                MapUtil.getInt(params, "pagesize", 5), UserThreadLocal.getUserId());

        List<RecommendUser> items = (List<RecommendUser>) pageResult.getItems();
        if (CollUtil.isEmpty(items)) {
            throw new MyException(ErrorResult.recommendUserIsEmpty());
        }

        // 3.从第2步的结果集中来提取userId 去查询tb_user_info
        List<Long> userIds = CollUtil.getFieldValues(items, "userId", Long.class);

        // 调用Dubbo去查询List<UserInfo>
        UserInfo userInfo = new UserInfo();
        userInfo.setSex(MapUtil.getStr(params, "gender"));
        userInfo.setCity(MapUtil.getStr(params, "city"));
        userInfo.setAge(MapUtil.getInt(params, "age"));

        Map<Long, UserInfo> userInfoMap = userInfoService.findUserInfoListByUserIds(userInfo, userIds);

        // 把第2步和第3步的结果集 合并成一个VO
        List<TodayBestVo> voList = new ArrayList<>();
        if (MapUtil.isEmpty(userInfoMap)) {
            pageResult.setItems(Collections.emptyList());
            return pageResult;
        }

        for (RecommendUser recommendUser : items) {
            TodayBestVo best = TodayBestVo.init(userInfoMap.get(recommendUser.getUserId()), recommendUser);
            if (ObjectUtil.isNotNull(best)) {
                voList.add(best);
            }
        }
        pageResult.setItems(voList);
        return pageResult;
    }

    /**
     * 个人主页上的个人信息
     *
     * @param userId
     * @return
     */
    public TodayBestVo queryUserInfo(Long userId) {
        // 保存来访者信息
        visitorsService.saveVisitor(userId);

        // 根据用户的id查询用户的信息
        UserInfo userinfo = userInfoService.findUserInfoByUserId(userId);
        // 根据用户id和登录人的id查询他们的缘分值
        RecommendUser recommendUser = recommendUserApi.queryScoreByUserId(UserThreadLocal.getUserId(), userId);
        // 把上面两步的结果封装到一个VO中
        TodayBestVo todayBest = new TodayBestVo();
        todayBest.setId(userinfo.getUserId());
        todayBest.setAvatar(userinfo.getLogo());
        todayBest.setNickname(userinfo.getNickName());
        todayBest.setGender(userinfo.getSex() == 1 ? "man" : "woman");
        todayBest.setAge(userinfo.getAge());
        todayBest.setTags(StrUtil.splitToArray(userinfo.getTags(), ","));
        todayBest.setFateValue(Convert.toLong(recommendUser.getScore()));
        todayBest.setFateValue(Convert.toLong(recommendUser.getScore()));
        return todayBest;
    }

    /**
     * 根据一个人的id查询他设置的问题
     *
     * @param userId
     * @return
     */
    public String queryQuestion(Long userId) {
        Question question = questionApi.findQuestionByUserId(userId);
        if (ObjectUtil.isEmpty(question)) {
            return "你的爱好是什么?";
        }
        return question.getTxt();
    }

    /**
     * 回复陌生人问题
     *
     * @param userId
     * @param reply
     */
    public void replyQuestion(Long userId, String reply) {
        /*
        userId:  申请人ID  登录人的ID                     已知
        huanXinId:  申请人的环信ID  登录人的环信ID          已知
        nickname: 申请人的昵称  登录人的昵称                没有  自己查询数据库
        strangerQuestion:  被申请人设置的问题              没有  自己查询数据库
        reply:  申请人的回答内容                           没有  传递
        被申请人的ID                                      没有  传递

        {"userId":1,"huanXinId":"HX_1","nickname":"黑马小妹",
        "strangerQuestion":"你喜欢去看蔚蓝的大海还是去爬巍峨的高山？",
        "reply":"我喜欢秋天的落叶，夏天的泉水，冬天的雪地，只要有你一切皆可~"}
       */

        // 查询申请人/登录人的昵称
        UserInfo userInfo = userInfoService.findUserInfoByUserId(UserThreadLocal.getUserId());

        // 查询被申请人的问题
        Question question = questionApi.findQuestionByUserId(userId);

        // 拼凑数据
        HashMap<String, Object> mm = new HashMap<>();
        mm.put("userId", userInfo.getUserId());
        mm.put("huanXinId", "HX_" + userInfo.getUserId());
        mm.put("nickname", userInfo.getNickName());
        mm.put("strangerQuestion", ObjectUtil.isEmpty(question) ? "你的爱好是什么?" : question.getTxt());
        mm.put("reply", reply);

        // 给环信发送请求
        if (!hxService.sendMsgFromAdmin("HX_" + userId, JSONUtil.toJsonStr(mm))) {
            throw new MyException(ErrorResult.sendHXMsgFailed());
        }
    }

    /**
     * 上传/更新用户位置信息
     *
     * @param longitude
     * @param latitude
     * @param address
     */
    public void updateLocation(Double longitude, Double latitude, String address) {
        Boolean flag = userLocationApi.updateUserLocation(UserThreadLocal.getUserId()
                , longitude, latitude, address);
        if (!flag) {
            throw new MyException(ErrorResult.updateUserLocationFailed());
        }
    }

    /**
     * 搜索附近的人
     *
     * @param gender
     * @param distance
     * @return
     */
    public List<NearUserVo> queryNearUser(String gender, Double distance) {
        // 查找自己的位置信息
        UserLocationVo userLocationVo = userLocationApi.queryByUserId(UserThreadLocal.getUserId());
        // 搜索附近的人
        List<UserLocationVo> userLocationVos = userLocationApi.queryUserFromLocation(userLocationVo.getLongitude(),
                userLocationVo.getLatitude(), distance, 50);
        // 提取附近的人的ID
        List<Long> userIds = CollUtil.getFieldValues(userLocationVos, "userId", Long.class);
        if (CollUtil.isEmpty(userIds)) {
            return Collections.EMPTY_LIST;
        }
        // 查询tb_user_info
        Map<Long, UserInfo> userInfoMap = userInfoService.findUserInfoListByUserIds(UserInfo.builder().sex("man".equalsIgnoreCase(gender) ? 1 : 2).build(), userIds);
        // 拼凑VO对象
        List<NearUserVo> nearUserVoList = new ArrayList<>();
        for (UserInfo info : userInfoMap.values()) {
            // 排除自己
            if (info.getUserId() == UserThreadLocal.getUserId()) {
                continue;
            }
            NearUserVo nearUserVo = new NearUserVo();
            nearUserVo.setUserId(info.getUserId());
            nearUserVo.setAvatar(info.getLogo());
            nearUserVo.setNickname(info.getNickName());
            nearUserVoList.add(nearUserVo);
        }
        return nearUserVoList;
    }

    /**
     * 首页探花功能卡片数据查询
     *
     * @return
     */
    public List<TodayBestVo> queryCardsList() {
        // 查询推荐的人的列表
        List<Long> exUserIds = new ArrayList<>();
        // 自己喜欢的人的列表
        Collection<String> union = CollUtil.union(redisTemplate.opsForSet().members(Constants.USER_LIKE_KEY + UserThreadLocal.getUserId()),
                redisTemplate.opsForSet().members(Constants.USER_NOT_LIKE_KEY + UserThreadLocal.getUserId()));
        for (String s : union) {
            exUserIds.add(Convert.toLong(s));
        }

        List<RecommendUser> recommendUsers = recommendUserApi.queryCardsList(UserThreadLocal.getUserId(), 30, exUserIds);
        // 要从上面的结果集中提取 userId
        List<Long> userIds = CollUtil.getFieldValues(recommendUsers, "userId", Long.class);
        // 查询tb_user_info
        Map<Long, UserInfo> userInfoMap = userInfoService.findUserInfoListByUserIds(null, userIds);
        // 拼凑VO对象
        List<TodayBestVo> todayBestVoList = new ArrayList<>();
        for (RecommendUser recommendUser : recommendUsers) {
            TodayBestVo todayBest = new TodayBestVo();
            UserInfo info = userInfoMap.get(recommendUser.getUserId());
            todayBest.setId(info.getUserId());
            todayBest.setAvatar(info.getLogo());
            todayBest.setNickname(info.getNickName());
            todayBest.setGender(info.getSex() == 1 ? "man" : "woman");
            todayBest.setAge(info.getAge());
            todayBest.setTags(StrUtil.splitToArray(info.getTags(), ","));
            todayBest.setFateValue(Convert.toLong(recommendUser.getScore()));
            todayBestVoList.add(todayBest);
        }

        return todayBestVoList;
    }

    /**
     * 探花卡片右滑喜欢功能
     *
     * @param likeUserId
     */
    public void likeUser(Long likeUserId) {
        // 先往user_like表中添加一条记录
        UserLike userLike = new UserLike();
        userLike.setId(new ObjectId());
        userLike.setUserId(UserThreadLocal.getUserId());
        userLike.setLikeUserId(likeUserId);
        userLike.setCreated(System.currentTimeMillis());
        userLikeApi.likeUser(userLike);

        // 把喜欢的人的id缓存到redis中
        redisTemplate.opsForSet().add(Constants.USER_LIKE_KEY + UserThreadLocal.getUserId(), likeUserId.toString());
    }

    /**
     * 探花卡片左滑不喜欢功能
     *
     * @param likeUserId
     */
    public void notLikeUser(Long likeUserId) {
        redisTemplate.opsForSet().add(Constants.USER_NOT_LIKE_KEY + UserThreadLocal.getUserId(), likeUserId.toString());
    }
}
